#include "Utility.h"

#include "../Main/Standard.h"

namespace Utility
{
	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <Summary>	String Copy	</Summary>
	///
	/// <Param name="str">	The string to be copied </Param>
	///
	/// <Return>	A copy of the passed in string </Return>
	///
	/// <Remarks>	
	///		This function calls new[] to create the data, you must remember to delete it
	///	</Remarks>
	////////////////////////////////////////////////////////////////////////////////////////////////////
	char* StrCpy(const char* const str)
	{
		const unsigned int count = strlen(str);

		char* retstr = new char[count + 1];

		strcpy_s(retstr, count + 1, str);

		return retstr;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <Summary>	Create Hash	</Summary>
	///
	/// <Param name="str">	The string to be referenced for the hash code </Param>
	///
	/// <Return>	The newly created hash code </Return>
	////////////////////////////////////////////////////////////////////////////////////////////////////
	unsigned long CreateHash(const char* str)
	{
		const unsigned long BASE = 65521L;

		const unsigned long MAX = 5552L;

		#define DO1(buf, i) { s1 += toupper(buf[i]); s2 += s1; }
		#define DO2(buf, i) DO1(buf, i); DO1(buf, i + 1);
		#define DO4(buf, i) DO2(buf, i); DO2(buf, i + 2);
		#define DO8(buf, i) DO4(buf, i); DO4(buf, i + 4);
		#define DO16(buf)	DO8(buf, 0); DO8(buf, 8);

		if(str == NULL)
			return NULL;

		unsigned long s1 = 0;
		unsigned long s2 = 0;

		for(unsigned len = strlen(str); len > 0;)
		{
			unsigned long k = len < MAX ? len : MAX;

			len -= k;

			while(k >= 16)
			{
				DO16(str);
				str += 16;
				k -= 16;
			}

			if(k != 0)
			{
				do
				{
					s1 += *str++;
					s2 += s1;
				}
				while(--k);
			}

			s1 %= BASE;
			s2 %= BASE;
		}

		return ( (s2 << 16) | s1 );

		#undef DO1
		#undef DO2
		#undef DO4
		#undef DO8
		#undef DO16
	}

	unsigned int HashFuncInt(const int& num)
	{
		return (unsigned int)num;
	}

	unsigned int HashFuncShort(const short& num)
	{
		return (unsigned int)num;
	}

	unsigned int HashFuncLong(const long& num)
	{
		return (unsigned int)num;
	}

	unsigned int HashFuncUInt(const unsigned int& num)
	{
		return (unsigned int)num;
	}

	unsigned int HashFuncUShort(const unsigned short& num)
	{
		return (unsigned int)num;
	}

	unsigned int HashFuncULong(const unsigned long& num)
	{
		return (unsigned int)num;
	}

};